package com.suke.czx.authentication.detail;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.suke.czx.common.utils.CodeConstant;
import com.suke.czx.common.utils.Constant;
import com.suke.czx.modules.sys.entity.SysUser;
import com.suke.czx.modules.sys.service.PermissionsService;
import com.suke.czx.modules.sys.service.SysUserService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

/**
 * 应用模块名称: 登录用户
 * 代码描述: 登录用户业务
 * copyright: AUZAR ALL RIGHTS RESERVED
 * company: AUZAR
 *
 * @author: 颜米晨
 * @date: 2021/08/27 16:31
 */
@Component
public class CustomUserDetailsService implements UserDetailsService {

    @Resource
    private SysUserService sysUserService;

    @Resource
    private PermissionsService permissionsService;

    @Resource
    private RedisTemplate redisTemplate;


    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        SysUser sysUser = sysUserService.getOne(Wrappers.<SysUser>query().lambda().eq(SysUser::getUsername, username));
        if (ObjectUtil.isNull(sysUser)) {
            throw new UsernameNotFoundException("用户不存在");
        }
        if (sysUser.getStatus() == null || sysUser.getStatus().intValue() == CodeConstant.STATUS_FORBIDDEN) {
            throw new UsernameNotFoundException("账户已被禁用");
        }
        return getPermissionsByDataBase(sysUser);
    }

    public UserDetails loadUserByUserId(Long userId) throws UsernameNotFoundException {
        SysUser sysUser = sysUserService.getById(userId);
        if (ObjectUtil.isNull(sysUser)) {
            throw new UsernameNotFoundException("用户不存在");
        }
        return getPermissionsByRedis(sysUser);
    }

    private UserDetails getPermissionsByDataBase(SysUser sysUser) {
        Set<String> permissions =  permissionsService.getUserPermissions(sysUser.getUserId());
        return handlePermission(sysUser, permissions, "ROLE_");
    }

    private UserDetails getPermissionsByRedis(SysUser sysUser) {
        String auth = StrUtil.toString(redisTemplate.opsForValue().get(Constant.AUTHENTICATED + Constant.COLON + sysUser.getUserId()));
        Set<String> permissions = new HashSet<>(Arrays.asList(StrUtil.split(auth, Constant.COMMA)));
        return handlePermission(sysUser, permissions, Constant.BLANK);
    }

    private UserDetails handlePermission(SysUser sysUser, Set<String> permissions, String permissionPrefix) {
        String[] roles = new String[0];
        if (CollUtil.isNotEmpty(permissions)) {
            roles = permissions.stream().map(role -> permissionPrefix + role).toArray(String[]::new);
        }
        Collection<? extends GrantedAuthority> authorities  = AuthorityUtils.createAuthorityList(roles);
        return new CustomUserDetailsUser(sysUser.getUserId(), sysUser.getUsername(), sysUser.getPassword(), authorities);
    }

}
